/* eslint-disable @typescript-eslint/explicit-module-boundary-types */
/* eslint-disable no-use-before-define */
/* eslint-disable no-shadow */
import { computed, ref } from 'vue';
import type { SetupContext } from 'vue';
import {
  CalendarDailyEmits,
  CalendarDailyProps,
  IEvent,
  IUIEvent,
  IUILegend,
} from '../interface';
import {
  fade,
  handleBkColor,
  handleEVentClick,
  handleTimeRange,
  isToday,
} from '../util';

export const useCalendarDaily = (
  props: CalendarDailyProps,
  emit: SetupContext<CalendarDailyEmits>['emit'],
) => {
  const drawData = ref<string[]>([]);
  const curTimeTimer = ref();
  const curTimeTop = ref(0);
  const curTimeVal = ref('00:00');
  const resizableHand = ref();
  const calendarDaily = ref();
  const legends = computed(() => props.legends || []);
  const multiple = computed(() => props.multiple === true);
  const selectedData = ref<IEvent[]>([]);

  // 记录初始鼠标位置和要改变大小的元素的初始大小
  let initialMouseY = 0;
  let initialHeight = 0;
  /**
   * @description 开始拖动，初始化节点数据
   * @param {DragEvent} event
   */
  const handleDragStart = (event: DragEvent) => {
    initialMouseY = (event as IParams).clientY;
    initialHeight = parseInt(
      window.getComputedStyle(resizableHand.value).height,
      10,
    );
  };

  /**
   * @description 处理拖动
   * @param {DragEvent} event
   */
  const handleDrag = (event: DragEvent) => {
    const heightChange: number =
      (event as IParams).clientY - initialMouseY + initialHeight;
    resizableHand.value.style.height = `${heightChange}px`;
  };

  /**
   * @description 事件数据集合
   * @returns {IData}
   */
  const events = computed(() => {
    // eslint-disable-next-line no-use-before-define
    return computeUIEvents(
      props.events,
      props?.selectedDay,
      legends.value,
      calendarDaily.value,
    );
  });

  /**
   * @description 计算events数据
   * @param {IUIEvent[]} events
   * @returns {IEvent[]}
   */
  const computeUIEvents = (
    events: IUIEvent[],
    curDate: Date,
    legends: IUILegend[],
    calendarDaily: HTMLElement,
  ) => {
    const tempEvents: IUIEvent[] = [];
    const tempColors = new Map();
    let contentWidth = 0;
    if (calendarDaily) {
      contentWidth = parseInt(window.getComputedStyle(calendarDaily).width, 10);
    }
    // 排序处理事件显示顺序
    events.sort((a: IUIEvent, b: IUIEvent) => {
      const beginTimeDifference =
        new Date(a.beginTime).getTime() - new Date(b.beginTime).getTime();
      let type;
      if (beginTimeDifference === 0) {
        type = new Date(a.endTime).getTime() - new Date(b.endTime).getTime();
      } else {
        type = beginTimeDifference;
      }
      return type;
    });
    // 过滤数组
    const tempArray: IUIEvent[] = events.filter((event: IUIEvent) => {
      return (
        event &&
        event.beginTime &&
        event.endTime &&
        isToday(curDate, event.beginTime) &&
        isToday(curDate, event.endTime)
      );
    });
    // 处理绘制需要的UI参数
    tempArray.forEach((event: IUIEvent, index: number) => {
      const tempItem = {} as IUIEvent;
      Object.assign(tempItem, event);
      const targetLegend = legends.find((legendItem: IUILegend) =>
        Object.is(legendItem.id, event.itemType),
      );
      const targetEvent = selectedData.value.find(
        (item: IUIEvent) => item.id === event.id,
      );
      Object.assign(tempItem, { zIndex: index + 1 });
      const length = tempArray.length;
      const itemWidth = (contentWidth - 90) / length;
      // 计算宽度
      const percentage: number = Number((100 / length).toFixed(3));
      let width = `${percentage}%`;
      // 计算定位
      let styleLeft = `${index * percentage}%`;
      if (itemWidth < 100) {
        width = '100px';
        styleLeft = `${index * 100}px`;
      }
      Object.assign(tempItem, { width, styleLeft });
      // 计算高度
      if (event.beginTime && event.endTime) {
        const height = handleEventHeight(
          event.beginTime,
          event.endTime,
          curDate,
        );
        const timeRange = handleTimeRange(
          event.beginTime,
          event.endTime,
          'HH:mm',
        );
        Object.assign(tempItem, { height, timeRange });
      }
      if (event.beginTime) {
        const { styleTop } = handleTopOrCurVal(new Date(event.beginTime));
        Object.assign(tempItem, { styleTop });
      }
      if (!event?.bkColor) {
        const bkColor = targetLegend
          ? targetLegend.bkcolor
          : handleBkColor(tempColors, event.itemType);
        Object.assign(tempItem, { bkColor });
      }
      if (tempItem.bkColor) {
        const tempBkColor = fade(tempItem.bkColor, 10);
        Object.assign(tempItem, {
          bkColorFade: tempBkColor,
        });
      }
      // 计算边框显示
      if (tempItem?.height && (tempItem as IParams)?.height > 10) {
        const border = '1px solid #FFF';
        Object.assign(tempItem, { border });
      } else {
        Object.assign(tempItem, { border: 'none' });
      }
      // 判断事件是否默认选中
      if (targetEvent) {
        Object.assign(tempItem, { isSelectedEvent: true });
      } else {
        Object.assign(tempItem, { isSelectedEvent: false });
      }
      // 图例过滤
      if ((targetLegend && targetLegend.isShow) || !targetLegend) {
        tempEvents.push(tempItem);
      }
    });
    tempColors.clear();
    return tempEvents;
  };

  /**
   * @description 处理事件卡片展示高度
   * @param {string | Date} startTime
   * @param {string | Date} endTime
   * @returns {number}
   */
  const handleEventHeight = (
    startTime: string | Date,
    endTime: string | Date,
    date: Date,
  ) => {
    let height = 1;
    if (isToday(startTime, date) && isToday(endTime, date)) {
      const difference =
        new Date(endTime).getTime() - new Date(startTime).getTime();
      height = Math.floor(difference / (1000 * 60));
    }
    if (height < 3) {
      height = 3;
    }
    return height;
  };

  /**
   * @description 处理定位高度及当前时间显示值
   * @param {Date} date
   * @returns {{number, string}} {styleTop, timeVal}
   */
  const handleTopOrCurVal = (date: Date) => {
    const currentHours = date.getHours();
    const currentMinutes = date.getMinutes();
    const hours = String(currentHours).padStart(2, '0');
    const minutes = String(currentMinutes).padStart(2, '0');
    let styleTop;
    let timeVal;
    if (currentHours === 0 && currentMinutes === 0) {
      styleTop = 0;
      timeVal = '00:00';
    } else {
      const topVal = currentHours * 60 + currentMinutes;
      styleTop = topVal;
      timeVal = `${hours}:${minutes}`;
    }
    return { styleTop, timeVal };
  };

  /**
   * @description 处理当前时间显示内容及定位高度
   */
  const handleCurTime = () => {
    const { styleTop, timeVal } = handleTopOrCurVal(new Date());
    curTimeTop.value = styleTop;
    curTimeVal.value = timeVal;
  };

  /**
   * @description 初始化数据
   * @returns {string[]}
   */
  const initDrawData = () => {
    const tempDrawData = [];
    for (let i = 1; i < 24; i++) {
      const hours = String(i).padStart(2, '0');
      const timescale = `${hours}:00`;
      tempDrawData.push(timescale);
    }
    return tempDrawData;
  };

  /**
   * @description 事件点击
   * @param {IUIEvent} item
   * @param {string} location
   */
  const eventClick = async (item: IUIEvent, location: string) => {
    const res = await handleEVentClick(
      item,
      location,
      props.events,
      multiple.value,
      selectedData.value,
      emit,
    );
    const { tempSelectedData, isSelectedEvent } = res as IParams;
    if (!isSelectedEvent) {
      Object.assign(item, { isSelectedEvent });
    }
    selectedData.value = tempSelectedData;
  };

  return {
    drawData,
    curTimeTimer,
    curTimeTop,
    curTimeVal,
    events,
    resizableHand,
    calendarDaily,
    selectedData,
    handleCurTime,
    handleDrag,
    handleDragStart,
    eventClick,
    initDrawData,
  };
};
